home *** CD-ROM | disk | FTP | other *** search
- /***
- * MemoryBuffer.c
- *
- * Routines to implement a very simple memory allocation scheme. None of the sphofistication
- * of the real mac memory manager here. In fact, we don't even deal with "freeing" a
- * string! We just ignore it. This is meant as a short term way of packing some data
- * like strings together (to avoid the 255 limit and space wasted in that scheme).
- *
- ***/
- #include "MemoryBuffer.h"
- #include "Exceptions.h"
-
- typedef struct {
- short checkVersion;
- short increaseSize;
- short freeBytes;
- short offsetToFreeBlock;
- } bufferHeader, *bufferHeaderPtr;
-
- #define CHECK_VERSION 0xAF01
-
- OSErr MBAddToBuffer (Handle buffer, short length);
-
- /**
- * NewMemoryBuffer
- *
- * Return a pointer to a new inited area we can allocate some strings from
- *
- **/
- OSErr NewMemoryBuffer (Handle *buffer, short initalSize, short increase)
- {
- OSErr theErr;
- bufferHeaderPtr bufHdr;
-
- /**
- ** Make sure incomming params are OK
- **/
-
- theErr = paramErr;
- require (initalSize > (sizeof(short)*2)
- || increase < 0, BadParameters);
-
- /**
- ** Ok, allocate the inital size
- **/
-
- *buffer = NewHandleClear (initalSize);
- theErr = MemError ();
- if (theErr == noErr && *buffer == 0)
- theErr = memFullErr;
- nrequire (theErr, FailedToAllocateMemory);
-
- /**
- ** Fill in the increase size argument, and also the offset to the first free
- ** block... which is just two!
- **/
-
- bufHdr = (bufferHeaderPtr) **buffer;
- bufHdr -> checkVersion = CHECK_VERSION;
- bufHdr -> increaseSize = increase;
- bufHdr -> freeBytes = initalSize - sizeof (bufferHeader);
- bufHdr -> offsetToFreeBlock = sizeof (bufferHeader);
-
- /**
- ** Done!
- **/
-
- return noErr;
-
- /**
- ** Deal with errors...
- **/
-
- FailedToAllocateMemory: // Couldn't allocate memory for the inital buffer!
-
- BadParameters: // Didn't tell us something right!
- *buffer = 0;
- return theErr;
- }
-
- /**
- * DisposeMemoryBuffer
- *
- * Get rid of the buffer
- *
- **/
- OSErr DisposeMemoryBuffer (Handle buffer)
- {
- bufferHeaderPtr bufHdr;
-
- require (buffer != 0
- && *buffer != 0, BadParams);
-
- bufHdr = (bufferHeaderPtr) *buffer;
- require (bufHdr->checkVersion == CHECK_VERSION, BadParamsPrime);
-
- DisposeHandle (buffer);
- return noErr;
-
- BadParamsPrime:
- BadParams:
-
- return paramErr;
- }
-
- /**
- * MBSaveString
- *
- * Save a string in the current buffer. Save the string as the string and the length
- * of the string (as a short).
- *
- **/
- OSErr MBSaveString (Handle buffer, char *string, short length, short *offset)
- {
- OSErr theErr;
- bufferHeaderPtr bufHdr;
-
- /**
- ** Make sure our parameters are done right!
- **/
-
- theErr = paramErr;
- require (buffer != 0
- && *buffer != 0
- && string != 0
- && length > 0, BadParams);
-
- bufHdr = (bufferHeaderPtr) *buffer;
- require (bufHdr->checkVersion == CHECK_VERSION, BadParamsPrime);
-
- /**
- ** Allocate the memory -- note that bufHdr may be invalid after the
- ** return of this routine... cause the darn thing might have moved in
- ** memory during allocation!
- **/
-
- theErr = MBAllocateBuffer (buffer, length + sizeof(short), offset);
- nrequire (theErr, FailedToAllocateMemory);
-
- /**
- ** Move over the "short" index and copy the string in!
- **/
-
- *((short *) (*buffer + *offset)) = length;
- BlockMove (string, *buffer + *offset + sizeof(short), length);
-
- return noErr;
-
- /**
- ** Handle errors!
- **/
- FailedToAllocateMemory: // Not enough memory in here! :(
-
- BadParamsPrime:
- BadParams: // Something unhealthy came our way!
-
- *offset = 0; // Make sure they can't do anything with this!
- return theErr;
- }
-
- /**
- * MBGetPString
- *
- * Get a string, and return it in a pascal format. Truncate if too long.
- *
- **/
- OSErr MBGetPString (Handle buffer, short offset, StringPtr string)
- {
- OSErr theErr;
- bufferHeaderPtr bufHdr;
- short length;
-
- /**
- ** Make sure our parameters are done right!
- **/
-
- theErr = paramErr;
- require (buffer != 0
- && *buffer != 0
- && offset >= sizeof(bufferHeader), BadParams);
-
- bufHdr = (bufferHeaderPtr) *buffer;
- require (bufHdr->checkVersion == CHECK_VERSION, BadParamsPrime);
-
- require (bufHdr->offsetToFreeBlock > offset, BadParamsPrime2);
-
- /**
- ** Ok -- now get out the length of the string, and figure out how
- ** much we should copy...
- **/
-
- length = *((short *) &((*buffer)[offset]));
- theErr = -1;
- require (length + offset < bufHdr->offsetToFreeBlock, BadOffset);
-
- if (length > sizeof (Str255))
- length = sizeof (Str255);
-
- string[0] = length;
- BlockMove (*buffer + offset + 2, &(string[1]), string[0]);
-
- return noErr;
-
- /**
- ** Errors
- **/
- BadOffset: // The offset into the array didn't make any sense!
-
- BadParamsPrime2:
-
- BadParamsPrime: // Got something evil in the mail!
- BadParams:
-
- string[0] = 0;
-
- return theErr;
- }
-
- /**
- * MBAllocateBuffer
- *
- * Allocate some space in the buffer. If there isn't enough room, then we had
- * better add some!
- *
- **/
- OSErr MBAllocateBuffer (Handle buffer, short length, short *offset)
- {
- OSErr theErr;
- bufferHeaderPtr bufHdr;
-
- /**
- ** Make sure that our params are ok...
- **/
-
- theErr = paramErr;
- require (buffer != 0
- && length > 0, BadParams);
-
- bufHdr = (bufferHeaderPtr) *buffer;
- require (bufHdr->checkVersion == CHECK_VERSION, BadParamsPrime);
-
- /**
- ** First, determine if there is enough memory to allocate. If
- ** not, get it.
- **/
-
- if (bufHdr -> freeBytes < (length + sizeof (short))) {
- theErr = MBAddToBuffer (buffer, length+sizeof(short));
- nrequire (theErr, FailedToGetEnoughMem);
- bufHdr = (bufferHeaderPtr) *buffer;
- }
-
- /**
- ** Great. Now update the pointer stuff in the header...
- **/
-
- *offset = bufHdr -> offsetToFreeBlock;
- bufHdr -> offsetToFreeBlock += length;
- bufHdr -> freeBytes -= length;
-
- return noErr;
-
- /**
- ** Errors
- **/
-
- FailedToGetEnoughMem: // Couldn't make the buffer big enough!
-
- BadParamsPrime:
- BadParams: // We were given something evil!
-
- return theErr;
-
- }
-
- /**
- * MBAddToBuffer
- *
- * Ok -- length is bigger than the free space we have. Job is to allocate
- * new free space -- do it increaseSize bytes at a time. Make sure we have
- * atleast 1/4 of the increaseSize left over at the end of the game so we don't
- * end up doing another allocation right away...
- *
- **/
- OSErr MBAddToBuffer (Handle buffer, short length)
- {
- OSErr theErr;
- bufferHeaderPtr bufHdr;
- short bytesNeeded, bytesToAllocate;
- short blocksNeeded;
-
- /**
- ** Make sure that our params are ok...
- **/
-
- theErr = paramErr;
- require (buffer != 0
- && length > 0, BadParams);
-
- bufHdr = (bufferHeaderPtr) *buffer;
- require (bufHdr->checkVersion == CHECK_VERSION, BadParamsPrime);
-
- /**
- ** Calculate how many bytes are needed, and convert that
- ** into the number of blocks we want to get.
- **/
-
- theErr = -1;
- bytesNeeded = length - bufHdr->freeBytes;
- require (bytesNeeded > 0, BytesNeededNotZero);
-
- blocksNeeded = bytesNeeded / bufHdr->increaseSize;
- if ((blocksNeeded*bufHdr->increaseSize - bytesNeeded)
- < (bufHdr->increaseSize/4))
- blocksNeeded++;
-
- bytesToAllocate = bufHdr->increaseSize * blocksNeeded;
-
- /**
- ** Ok -- we can now do our stuff
- **/
-
- SetHandleSize (buffer, GetHandleSize (buffer) + bytesToAllocate);
- theErr = MemError ();
- require (theErr, FailedToGetMoreMemory);
-
- return noErr;
-
- /**
- ** Errors
- **/
-
- FailedToGetMoreMemory: // We couldn't allocate any memory just now. :(
-
- BytesNeededNotZero: // Bad internal programming error!!!!
-
- BadParamsPrime:
- BadParams: // We were given something evil!
-
- return theErr;
-
-
- }
-